package com.shop.om.utils;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import java.io.*;
import java.net.*;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;

/**
 * ClassName: HttpUtils
 * 
 * @Description: http请求工具类
 * @author apple
 * @date 2016年3月10日 下午3:57:14
 */
@SuppressWarnings("deprecation")
public class HttpUtils {
	private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class);

	/**
     * 请求类型： GET
     */
    public final static String GET = "GET";

	public final static String POST = "POST";
	/**
     * 模拟Http Get请求
     * @param urlStr
     *             请求路径
     * @return
     * @throws Exception
     */
    public static String get(String urlStr) throws Exception{
        HttpURLConnection conn = null;
        try{
            //创建URL对象
            URL url = new URL(urlStr);
            //获取URL连接
            conn = (HttpURLConnection) url.openConnection();
            //设置通用的请求属性
            setHttpUrlConnection(conn, GET);
            
            //建立实际的连接
            conn.connect();
            //获取响应的内容
            return readResponseContent(conn.getInputStream());
        }finally{
            if(null!=conn) conn.disconnect();
        }
    }
    
    /**
     * 设置Http连接属性 
     * @param conn
     *             http连接
     * @return
     * @throws ProtocolException 
     * @throws Exception 
     */
    private static void setHttpUrlConnection(HttpURLConnection conn, String requestMethod) throws ProtocolException{
        conn.setRequestMethod(requestMethod);
        
        conn.setRequestProperty("accept", "*/*");
        conn.setRequestProperty("Accept-Language", "zh-CN");
        conn.setRequestProperty("User-Agent", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)");
        conn.setRequestProperty("Proxy-Connection", "Keep-Alive");
        if(null!=requestMethod && POST.equals(requestMethod)){
            conn.setDoOutput(true);
            conn.setDoInput(true);
        }
    }
    
    /**
     * 读取响应字节流并将之转为字符串
     * @param in
     *         要读取的字节流
     * @return
     * @throws IOException
     */
    private static String readResponseContent(InputStream in) throws IOException{
        Reader reader = null;
        StringBuilder content = new StringBuilder();
        try{
            reader = new InputStreamReader(in, "UTF-8");
            char[] buffer = new char[1024];
            int head = 0;
            while( (head=reader.read(buffer))>0 ){
                content.append(new String(buffer, 0, head));
            }
    		return content.toString();
        }finally{
            if(null!=in) in.close();
            if(null!=reader) reader.close();
        }
    }
	/**
	 * @Description: http get请求共用方法
	 * @param @param reqUrl
	 * @param @param params
	 * @param @return
	 * @param @throws Exception
	 * @author apple
	 * @date 2016年3月10日 下午3:57:39
	 */
	@SuppressWarnings("resource")
	public static String sendGet(String reqUrl, Map<String, String> params,Map<String, String> headers)
			throws Exception {
		InputStream inputStream = null;
		HttpGet request = new HttpGet();
		try {
			String url = buildUrl(reqUrl, params);
			HttpClient client = new DefaultHttpClient();
			logger.info("========================="+url);
			for (Map.Entry<String, String> e : headers.entrySet()) {
		        	request.addHeader(e.getKey(), e.getValue());
		    }
			request.setURI(new URI(url));
			HttpResponse response = client.execute(request);
			inputStream = response.getEntity().getContent();
			String result = getJsonStringFromGZIP(inputStream);
			return result;
		} finally {
			if (inputStream != null) {
				inputStream.close();
			}
			request.releaseConnection();
		}

	}

	/**
	 * @Description: http post请求共用方法
	 * @param @param reqUrl
	 * @param @param params
	 * @param @return
	 * @param @throws Exception
	 * @author apple
	 * @date 2016年3月10日 下午3:57:53
	 */
	@SuppressWarnings("resource")
	public static String sendPost(String reqUrl, Map<String, String> params)
			throws Exception {
		try {
			Set<String> set = params.keySet();
			List<NameValuePair> list = new ArrayList<NameValuePair>();
			for (String key : set) {
				list.add(new BasicNameValuePair(key, params.get(key)));
			}
			if (list.size() > 0) {
				try {
					HttpClient client = new DefaultHttpClient();
					HttpPost request = new HttpPost(reqUrl);

					request.setHeader("Accept-Encoding", "gzip");
					request.setEntity(new UrlEncodedFormEntity(list, HTTP.UTF_8));

					HttpResponse response = client.execute(request);

					InputStream inputStream = response.getEntity().getContent();
					try {
						String result = getJsonStringFromGZIP(inputStream);

						return result;
					} finally {
						inputStream.close();
					}
				} catch (Exception ex) {
					ex.printStackTrace();
					throw new Exception("网络连接失败,请连接网络后再试");
				}
			} else {
				throw new Exception("参数不全，请稍后重试");
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new Exception("发送未知异常");
		}
	}
	
	/**
	 * @Description: http post请求json数据
	 * @param @param urls
	 * @param @param params
	 * @param @return
	 * @param @throws ClientProtocolException
	 * @param @throws IOException
	 * @author apple
	 * @date 2016年3月10日 下午3:58:15
	 */
	public static String sendPostBuffer(String urls, String params)
			throws ClientProtocolException, IOException {
		HttpPost request = new HttpPost(urls);

		StringEntity se = new StringEntity(params, HTTP.UTF_8);
		 se.setContentType("text/json");
		request.setEntity(se);
		request.setHeader("Content-Type", "application/json;charset=UTF-8");
		// 发送请求
		@SuppressWarnings("resource")
        HttpResponse httpResponse = new DefaultHttpClient().execute(request);
		// 得到应答的字符串，这也是一个 JSON 格式保存的数据
		String retSrc = EntityUtils.toString(httpResponse.getEntity());
		request.releaseConnection();
		return retSrc;

	}


	/**
	 * @Description: http post请求json数据
	 * @param @param urls
	 * @param @param params
	 * @param @return
	 * @param @throws ClientProtocolException
	 * @param @throws IOException
	 * @author apple
	 * @date 2016年3月10日 下午3:58:15
	 */
	public static String sendPostNotParam(String urls)
			throws ClientProtocolException, IOException {
		HttpPost request = new HttpPost(urls);

		/*StringEntity se = new StringEntity(params, HTTP.UTF_8);
		se.setContentType("text/json");
		request.setEntity(se);*/
		request.setHeader("Content-Type", "application/json;charset=UTF-8");
		// 发送请求
		@SuppressWarnings("resource")
        HttpResponse httpResponse = new DefaultHttpClient().execute(request);
		// 得到应答的字符串，这也是一个 JSON 格式保存的数据
		String retSrc = EntityUtils.toString(httpResponse.getEntity());
		request.releaseConnection();
		return retSrc;

	}


	/**
	 * @Description: http请求发送xml内容
	 * @param @param urlStr
	 * @param @param xmlInfo
	 * @param @return
	 * @author dapengniao
	 * @date 2016年3月10日 下午3:58:32
	 */
	public static String sendXmlPost(String urlStr, String xmlInfo) {
		// xmlInfo xml具体字符串
	    logger.info("\n请求参数:\n"+xmlInfo);
		try {
			URL url = new URL(urlStr);
			URLConnection con = url.openConnection();
			con.setDoOutput(true);
			con.setRequestProperty("Cache-Control", "no-cache");
			con.setRequestProperty("Content-Type", "text/xml");
			OutputStreamWriter out = new OutputStreamWriter(
					con.getOutputStream());
			out.write(new String(xmlInfo.getBytes("utf-8")));
			out.flush();
			out.close();
			BufferedReader br = new BufferedReader(new InputStreamReader(
					con.getInputStream()));
			String lines = "";
			for (String line = br.readLine(); line != null; line = br
					.readLine()) {
				lines = lines + line;
			}
			logger.info("\n请求结果:\n"+lines);
			
			return lines; // 返回请求结果
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return "fail";
	}


	private static String getJsonStringFromGZIP(InputStream is) {
		String jsonString = null;
		try {
			BufferedInputStream bis = new BufferedInputStream(is);
			bis.mark(2);
			// 取前两个字节
			byte[] header = new byte[2];
			int result = bis.read(header);
			// reset输入流到开始位置
			bis.reset();
			// 判断是否是GZIP格式
			int headerData = getShort(header);
			// Gzip 流 的前两个字节是 0x1f8b
			if (result != -1 && headerData == 0x1f8b) {
				// LogUtil.i("HttpTask", " use GZIPInputStream  ");
				is = new GZIPInputStream(bis);
			} else {
				// LogUtil.d("HttpTask", " not use GZIPInputStream");
				is = bis;
			}
			InputStreamReader reader = new InputStreamReader(is, "utf-8");
			char[] data = new char[100];
			int readSize;
			StringBuffer sb = new StringBuffer();
			while ((readSize = reader.read(data)) > 0) {
				sb.append(data, 0, readSize);
			}
			jsonString = sb.toString();
			bis.close();
			reader.close();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return jsonString;
	}

	private static int getShort(byte[] data) {
		return (data[0] << 8) | data[1] & 0xFF;
	}

	/**
	 * 构建get方式的url
	 * 
	 * @param reqUrl
	 *            基础的url地址
	 * @param params
	 *            查询参数
	 * @return 构建好的url
	 */
	public static String buildUrl(String reqUrl, Map<String, String> params) throws UnsupportedEncodingException{
		StringBuilder sbUrl = new StringBuilder();
    	sbUrl.append(reqUrl);
    	if (null != params) {
    		StringBuilder sbQuery = new StringBuilder();
        	for (Map.Entry<String, String> query : params.entrySet()) {
        		if (0 < sbQuery.length()) {
        			sbQuery.append("&");
        		}
        		if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) {
        			sbQuery.append(query.getValue());
                }
        		if (!StringUtils.isBlank(query.getKey())) {
        			sbQuery.append(query.getKey());
        			if (!StringUtils.isBlank(query.getValue())) {
        				sbQuery.append("=");
        				sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8"));
        			}        			
                }
        	}
        	if (0 < sbQuery.length()) {
        		sbUrl.append("?").append(sbQuery);
        	}
    	}
    	
    	return sbUrl.toString();
	}
	
	
	
	 /**
	    * 需要加密执行的
	    * @param url
	    * @param xmlInfo
	    * @return
	    * @throws Exception 
	    */
	   public static String postHttplientNeedSSL(String url,
	                                             String xmlInfo,
	                                             String cretPath,
	                                             String mrchId)
	         throws Exception{
	      //选择初始化密钥文件格式
	      KeyStore keyStore = KeyStore.getInstance("PKCS12");
	      //得到密钥文件流
	      FileInputStream instream = new FileInputStream(new File(cretPath));
	      try{
	         //用商户的ID 来解读文件
	         keyStore.load(instream, mrchId.toCharArray());
	      }finally{
	         instream.close();
	      }
	      //用商户的ID 来加载
	      SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mrchId.toCharArray()).build();
	      // Allow TLSv1 protocol only
	      SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
	      //用最新的httpclient 加载密钥
	      CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
	      StringBuffer ret = new StringBuffer();
	      try{
	         HttpPost httpPost = new HttpPost(url);
	         httpPost.setEntity(new StringEntity(xmlInfo));
	         CloseableHttpResponse response = httpclient.execute(httpPost);
	         try{
	            HttpEntity entity = response.getEntity();
	            if(entity != null){
	               BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));
	               String text;
	               while((text = bufferedReader.readLine()) != null){
	                  ret.append(text);
	               }
	            }
	            EntityUtils.consume(entity);
	         }finally{
	            response.close();
	         }
	      }finally{
	         httpclient.close();
	      }
	      return ret.toString();
	   }

   /**
	 * @Description: https 尿检仪 post请求json数据
	 * @param @param urls
	 * @param @param params
	 * @param @return
	 * @param @throws ClientProtocolException
	 * @param @throws IOException
	 * @author apple
	 * @throws IOException 
	 * @throws ClientProtocolException
	 * @date 2016年6月19日 下午3:58:15
	 */
	public static String sendPostHipee(String urls,String token) throws ClientProtocolException, IOException
			 {
		HttpGet request = new HttpGet(urls);
		  
		request.addHeader("token", token);
		request.addHeader("clientid", "123");
		request.addHeader("clienttype", "wx");
         
		// 发送请求
		@SuppressWarnings("resource")
        HttpResponse httpResponse = new DefaultHttpClient().execute(request);
		// 得到应答的字符串，这也是一个 JSON 格式保存的数据
		String retSrc = EntityUtils.toString(httpResponse.getEntity());
		request.releaseConnection();
		return retSrc;

	}
	
	 public static String sendPostCard(String url, JSONObject reqJson) {
         HttpClient client = new DefaultHttpClient();
         HttpPost post = new HttpPost(url);
         post.setHeader("Content-Type", "application/json");
         String result = "";
         try {
             StringEntity s = new StringEntity(reqJson.toString(), "utf-8");
             s.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE,
                     "application/json"));
             post.setEntity(s);
             // 发送请求
             HttpResponse httpResponse = client.execute(post);
 
             // 获取响应输入流
             InputStream inStream = httpResponse.getEntity().getContent();
             BufferedReader reader = new BufferedReader(new InputStreamReader(
                     inStream, "utf-8"));
             StringBuilder strber = new StringBuilder();
             String line = null;
             while ((line = reader.readLine()) != null)
                 strber.append(line + "\n");
             inStream.close();
             result = strber.toString();
             if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
            	 logger.info("请求服务器成功，做相应处理");
             } else {
            	 logger.info("请求服务端失败");
             }
         } catch (Exception e) {
        	 logger.info("请求异常");
             throw new RuntimeException(e);
         }
 
         return result;
     }
}
